package pl.pasu.ocrtc;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class DrawPanel extends SurfaceView implements SurfaceHolder.Callback {

    private RepaintingThread mThread;
    private ArrayList<Path> mPaths;
    private Paint mPaint;
    private Path mPath;
    private int mMoveEventsCount;
    private static final int MOVE_EVENTS_MAX_COUNT = 3;
    private static final int DRAW_COLOR = 0xFFFFFF00;
    private static final int[] CANVAS_BG_COLOR = {0xFF, 0x00, 0x00, 0x00};
    public static final long DRAWING_THREAD_SLEEP = 20;

    public DrawPanel(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaths = new ArrayList<Path>();
        mMoveEventsCount = 0;
        mPaint = new Paint();
        mPaint.setDither(true);
        mPaint.setColor(DRAW_COLOR);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(5);
        getHolder().addCallback(this);
        setFocusable(true);
    }

    public Bitmap getBitmapFromCanvas() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        doDraw(canvas);
        return bitmap;
    }

    public void clearImage() {
        synchronized (mThread.getSurfaceHolder()) {
            mPaths.clear();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        synchronized (mThread.getSurfaceHolder()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                mMoveEventsCount = 0;
                mPath = new Path();
                mPath.moveTo(event.getX(), event.getY());
                mPath.lineTo(event.getX(), event.getY());
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                ++mMoveEventsCount;
                mPath.lineTo(event.getX(), event.getY());
                if (mMoveEventsCount > MOVE_EVENTS_MAX_COUNT) {
                    mPaths.add(mPath);
                    mMoveEventsCount = 0;
                    mPath = new Path();
                    mPath.moveTo(event.getX(), event.getY());
                    mPath.lineTo(event.getX(), event.getY());
                }
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                mMoveEventsCount = 0;
                mPath.lineTo(event.getX() + 2, event.getY() + 2);
                mPaths.add(mPath);
            }
            return true;
        }
    }

    public void doDraw(Canvas canvas) {
        canvas.drawARGB(CANVAS_BG_COLOR[0], CANVAS_BG_COLOR[1], CANVAS_BG_COLOR[2], CANVAS_BG_COLOR[3]);
        for (Path path : mPaths) {
            canvas.drawPath(path, mPaint);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mThread = new RepaintingThread(getHolder(), this);
        mThread.setRunning(true);
        mThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mThread.setRunning(false);
        try {
            mThread.join();
        } catch (InterruptedException e) {
        }
    }
    class RepaintingThread extends Thread {

        private SurfaceHolder mSurfaceHolder;
        private DrawPanel mPanel;
        private boolean mRun = false;

        public RepaintingThread(SurfaceHolder surfaceHolder, DrawPanel panel) {
            mSurfaceHolder = surfaceHolder;
            mPanel = panel;
        }

        public void setRunning(boolean run) {
            mRun = run;
        }

        public boolean isRunning() {
            return mRun;
        }

        public SurfaceHolder getSurfaceHolder() {
            return mSurfaceHolder;
        }

        @Override
        public void run() {
            Canvas c;
            while (mRun) {
                c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        mPanel.doDraw(c);
                    }
                    if (DRAWING_THREAD_SLEEP > 0) {
                        Thread.sleep(DRAWING_THREAD_SLEEP);
                    }
                } catch (InterruptedException e) {
                } finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }
    }
}